package service

import (
	"VideoManageSystem/internal/initConfig"
	"VideoManageSystem/internal/model"
	"errors"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"go.uber.org/zap"
	"gorm.io/gorm"
)

// SaveVideo 保存视频到数据库
func SaveVideo(newVideo model.Video) error {
	err := initConfig.GormDb.Create(&newVideo).Error
	if err != nil {
		zap.L().Error("无法在数据库中保存新视频", zap.Error(err))
		return err
	}
	return nil
}

// GetVideoByID 根据ID查找视频
func GetVideoByID(id string) (*model.Video, error) {
	var video model.Video
	err := initConfig.GormDb.Where("id = ?", id).First(&video).Error
	if err != nil {
		zap.L().Error("无法找到该视频", zap.Error(err))
		return nil, err
	}
	return &video, nil
}

// UpdateVideo 更新视频信息
func UpdateVideo(video *model.Video) error {
	err := initConfig.GormDb.Save(video).Error
	if err != nil {
		zap.L().Error("无法更新视频信息", zap.Error(err))
		return err
	}
	return nil
}

func DeleteVideoByID(id string) error {
	// 获取 App 配置
	appConfig := initConfig.GetAppConfig()
	if appConfig == nil {
		zap.L().Error("配置未加载")
		return errors.New("配置未加载")
	}
	videoStoragePath := appConfig.Video.StoragePath // 如：E:/videos/

	// 查询视频记录
	var video model.Video
	result := initConfig.GormDb.Where("id = ?", id).First(&video)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			zap.L().Warn("未找到要删除的视频", zap.String("videoID", id))
			return result.Error
		}
		zap.L().Error("查询视频失败", zap.Error(result.Error))
		return result.Error
	}

	// 从 VideoURL 和 CoverURL 提取文件夹名
	videoUrl, err := url.Parse(video.VideoURL)
	if err != nil {
		zap.L().Error("解析视频 URL 失败", zap.String("url", video.VideoURL), zap.Error(err))
		return err
	}
	coverUrl, err := url.Parse(video.CoverURL)
	if err != nil {
		zap.L().Error("解析封面图片 URL 失败", zap.String("url", video.CoverURL), zap.Error(err))
		return err
	}

	// 假设 VideoURL 和 CoverURL 的格式为 http(s)://domain/videos/folder/video.mp4 和 http(s)://domain/videos/folder/cover.jpg
	// 我们需要提取 folder/video.mp4 和 folder/cover.jpg 然后进一步处理得到 folder
	videoRelativePath := strings.TrimPrefix(videoUrl.Path, "/videos/")
	videoFolder := filepath.Dir(videoRelativePath) // 得到文件夹名，如 monkey

	// 构造本地存储目录路径
	videoDirPath := filepath.Join(videoStoragePath, videoFolder)

	// 删除磁盘上的视频文件
	videoFilePath := filepath.Join(videoDirPath, filepath.Base(video.VideoURL))
	if _, err := os.Stat(videoFilePath); err == nil {
		// 文件存在，尝试删除
		if err := os.Remove(videoFilePath); err != nil {
			zap.L().Error("删除视频文件失败", zap.String("path", videoFilePath), zap.Error(err))
			return err
		}
	} else if !os.IsNotExist(err) {
		zap.L().Error("检查视频文件状态失败", zap.String("path", videoFilePath), zap.Error(err))
		return err
	}

	// 删除磁盘上的封面图片
	coverFilePath := filepath.Join(videoDirPath, filepath.Base(coverUrl.Path))
	if _, err := os.Stat(coverFilePath); err == nil {
		// 文件存在，尝试删除
		if err := os.Remove(coverFilePath); err != nil {
			zap.L().Error("删除封面图片失败", zap.String("path", coverFilePath), zap.Error(err))
			return err
		}
	} else if !os.IsNotExist(err) {
		zap.L().Error("检查封面图片状态失败", zap.String("path", coverFilePath), zap.Error(err))
		return err
	}

	// 尝试删除整个目录（如果目录为空）
	err = os.Remove(videoDirPath)
	if err != nil && !os.IsNotExist(err) {
		// 如果目录不为空或者有其他错误发生，则这里会返回错误。
		// 可以选择忽略非空目录的删除错误，因为可能还有其他文件。
		if strings.Contains(err.Error(), "directory not empty") {
			zap.L().Warn("无法删除视频目录，因为它不是空的", zap.String("dirPath", videoDirPath))
		} else {
			zap.L().Error("删除视频目录失败", zap.String("dirPath", videoDirPath), zap.Error(err))
			return err
		}
	}

	// 删除数据库记录
	deleteResult := initConfig.GormDb.Delete(&video)
	if deleteResult.Error != nil {
		zap.L().Error("删除视频记录失败", zap.Error(deleteResult.Error))
		return deleteResult.Error
	}

	zap.L().Info("视频删除成功",
		zap.String("videoID", id),
		zap.String("folderName", videoFolder),
		zap.String("dirPath", videoDirPath),
	)

	return nil
}

// GetVideoByIdFromSQL 根据ID查找视频
func GetVideoByIdFromSQL(id string) (model.Video, error) {
	query := `
		SELECT name, uploader, size, record_time, upload_time, id, content, video_url, cover_url, file_path
		FROM videos
		WHERE id = ?
	`

	// 定义参数
	args := []interface{}{id}

	var video model.Video

	// 执行查询
	rows, err := initConfig.SqlDb.Query(query, args...)
	if err != nil {
		zap.L().Error("执行查询失败",
			zap.String("query", query),
			zap.String("id", id),
			zap.Error(err))
		return video, err
	}
	defer func() {
		if rows != nil {
			if closeErr := rows.Close(); closeErr != nil {
				zap.L().Error("关闭查询结果集失败",
					zap.String("query", query),
					zap.Error(closeErr))
			}
		}
	}()

	// 解析结果
	if rows.Next() {
		err := rows.Scan(
			&video.Name,
			&video.Uploader,
			&video.Size,
			&video.RecordTime,
			&video.UploadTime,
			&video.ID,
			&video.Content,
			&video.VideoURL,
			&video.CoverURL,
			&video.FilePath,
		)
		if err != nil {
			zap.L().Error("解析用户数据失败", zap.Error(err))
			return video, err
		}
		// 返回成功
		return video, nil
	}

	// 检查是否有错误
	if err := rows.Err(); err != nil {
		zap.L().Error("遍历查询结果时出错", zap.Error(err))
		return video, err
	}

	// 没有找到记录
	return video, gorm.ErrRecordNotFound
}

type VideoListResult struct {
	Videos     []model.Video
	TotalCount int
}

// GetVideoListFromSQL 查找视频列表
func GetVideoListFromSQL(userInput struct {
	StartTime string `json:"startTime"`
	EndTime   string `json:"endTime"`
	Page      int    `json:"page"`
	Sort      string `json:"sort"`
	Search    string `json:"search"`
}) (VideoListResult, error) {
	// 基础查询语句（用于获取视频列表）
	baseQuery := `
		SELECT name, uploader, size, record_time, upload_time, id, content, video_url, cover_url, file_path
		FROM videos
		WHERE 1=1
	`

	// COUNT 查询语句（仅统计总数，不带 LIMIT/OFFSET）
	countQuery := `
		SELECT COUNT(*) 
		FROM videos
		WHERE 1=1
	`

	// 分别维护两个参数列表：
	var argsPage []interface{}  // 用于主查询（含分页）
	var argsCount []interface{} // 用于 COUNT 查询

	// 添加时间范围条件：上传时间在 startTime 到 endTime 之间
	if userInput.StartTime != "" && userInput.EndTime != "" {
		timeClause := " AND upload_time BETWEEN ? AND ?"
		baseQuery += timeClause
		countQuery += timeClause
		argsPage = append(argsPage, userInput.StartTime, userInput.EndTime)
		argsCount = append(argsCount, userInput.StartTime, userInput.EndTime)
	} else if userInput.StartTime != "" {
		// 只有开始时间
		timeClause := " AND upload_time >= ?"
		baseQuery += timeClause
		countQuery += timeClause
		argsPage = append(argsPage, userInput.StartTime)
		argsCount = append(argsCount, userInput.StartTime)
	} else if userInput.EndTime != "" {
		// 只有结束时间
		timeClause := " AND upload_time <= ?"
		baseQuery += timeClause
		countQuery += timeClause
		argsPage = append(argsPage, userInput.EndTime)
		argsCount = append(argsCount, userInput.EndTime)
	}

	// 添加搜索条件（用户名或电话模糊匹配）
	if userInput.Search != "" {
		searchClause := " AND (name LIKE ? OR content LIKE ?)"
		baseQuery += searchClause
		countQuery += searchClause

		// 为每个 ? 提供一个参数值，共两个
		argsPage = append(argsPage,
			"%"+userInput.Search+"%",
			"%"+userInput.Search+"%",
		)
		argsCount = append(argsCount,
			"%"+userInput.Search+"%",
			"%"+userInput.Search+"%",
		)
	}

	// 添加排序逻辑
	if userInput.Sort == "录制时间升序" {
		baseQuery += " ORDER BY STR_TO_DATE(record_time, '%Y-%m-%d') ASC"
	} else if userInput.Sort == "录制时间降序" {
		baseQuery += " ORDER BY STR_TO_DATE(record_time, '%Y-%m-%d') DESC"
	} else if userInput.Sort == "上传时间升序" {
		baseQuery += " ORDER BY STR_TO_DATE(upload_time, '%Y-%m-%d') ASC"
	} else if userInput.Sort == "上传时间降序" {
		baseQuery += " ORDER BY STR_TO_DATE(upload_time, '%Y-%m-%d') DESC"
	} else {
		// 默认按上传时间降序
		baseQuery += " ORDER BY STR_TO_DATE(upload_time, '%Y-%m-%d') DESC"
	}

	// 分页逻辑只作用于 baseQuery
	pageSize := 5
	if userInput.Page <= 0 {
		userInput.Page = 1
	}
	offset := (userInput.Page - 1) * pageSize
	baseQuery += " LIMIT ? OFFSET ?"
	argsPage = append(argsPage, pageSize, offset)

	// 执行 COUNT 查询
	var totalCount int
	err := initConfig.SqlDb.QueryRow(countQuery, argsCount...).Scan(&totalCount)
	if err != nil {
		zap.L().Error("执行计数查询失败",
			zap.String("query", countQuery),
			zap.Any("args", argsCount),
			zap.Error(err))
		return VideoListResult{}, err
	}

	// 执行主查询
	rows, err := initConfig.SqlDb.Query(baseQuery, argsPage...)
	if err != nil {
		zap.L().Error("执行查询失败",
			zap.String("query", baseQuery),
			zap.Any("args", argsPage),
			zap.Error(err))
		return VideoListResult{}, err
	}
	defer func() {
		if rows != nil {
			if closeErr := rows.Close(); closeErr != nil {
				zap.L().Error("关闭查询结果集失败", zap.Error(closeErr))
			}
		}
	}()

	// 解析结果
	var videoList []model.Video
	for rows.Next() {
		var video model.Video
		err := rows.Scan(
			&video.Name,
			&video.Uploader,
			&video.Size,
			&video.RecordTime,
			&video.UploadTime,
			&video.ID,
			&video.Content,
			&video.VideoURL,
			&video.CoverURL,
			&video.FilePath,
		)
		if err != nil {
			zap.L().Error("解析用户数据失败", zap.Error(err))
			continue
		}
		videoList = append(videoList, video)
	}

	if err := rows.Err(); err != nil {
		zap.L().Error("遍历查询结果时出错", zap.Error(err))
		return VideoListResult{}, err
	}

	return VideoListResult{
		Videos:     videoList,
		TotalCount: totalCount,
	}, nil
}
